Skip to content

fix(email): 修复重建 Date 邮件头时丢失时区 - #355

Merged
Jinnrry merged 1 commit into
Jinnrry:masterfrom
0clickjacking0:fix/preserve-email-date-timezone
Aug 17, 2026
Merged

Jinnrry merged 1 commit into
Jinnrry:masterfrom
0clickjacking0:fix/preserve-email-date-timezone

Conversation

@0clickjacking0

Copy link
Copy Markdown
Contributor

概要

  • 保存收到邮件的 Date 邮件头时保留时区偏移。
  • 将数据库模型转换回内部邮件类型时保留时间的时区信息。
  • 重建 MIME 邮件时优先解析新的 RFC3339 时间格式。
  • 继续兼容历史 YYYY-MM-DD HH:MM:SS 格式,并维持原有的本地时区解释方式。

问题

NewEmailFromReader 会把 RFC 5322 Date 邮件头解析成 time.Time,随后却使用 time.DateTime 格式保存。该格式不包含时区偏移。BuildBytes 重建邮件时,又使用 time.Local 解释同一个墙上时间,因此可能改变这个时间所代表的绝对时刻。

例如,输入时间 Sun, 09 Aug 2026 11:51:08 +0000 可能被重建成 Sun, 09 Aug 2026 11:51:08 +0800,使邮件头表示的绝对时刻向前偏移 8 小时,最终导致邮件客户端把刚收到的邮件显示为约 8 小时前发送。

NewEmailFromModel 也存在相同问题,因为它同样会把 SendDate 格式化为不含时区偏移的字符串。

修复方式

使用 RFC3339 保存解析得到的时间和模型时间,从而保留时区偏移。BuildBytes 重建邮件时优先按 RFC3339 解析;如果解析失败,再回退到历史无时区格式,确保数据库中已有的旧邮件仍能正常读取和重建。

测试

  • 验证邮件从读取到重建的完整过程不会改变原始绝对时刻。
  • 验证 UTC 时区的 models.Email.SendDate 重建后仍表示同一个绝对时刻。
  • 验证历史无时区 Date 数据仍按 time.Local 正常重建。

已执行:

TZ=Asia/Shanghai go test ./dto/parsemail -run 'TestEmail(DateFromReaderPreservesInstant|DateFromModelPreservesUTCInstant|BuildBytesAcceptsLegacyDate)$' -count=1
TZ=Asia/Shanghai go test ./dto/parsemail -count=1
git diff --check

@Jinnrry
Jinnrry merged commit cd8d549 into Jinnrry:master Aug 17, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants